/***************************************************************************
 *   Copyright (C) 2010 by Oleg Goncharov  *
 *   $EMAIL$                           *                          
 *                                                                         *
 *   This file is part of ChessVision.                                     *
 *                                                                         *
 *   ChessVision is free software; you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <opencv/cxcore.h>

CvSize cvCalcHoughSize(CvSize img_size, double rho, double teta) {
	return cvSize(int((2.0*sqrt(img_size.height*img_size.height + img_size.width*img_size.width) + 10.0) / rho), int(CV_PI / teta));
}

void cvHoughTransform(CvArr * src_image, CvArr * dst_image) 
{
	CV_FUNCNAME( "cvHoughTransform" );
	
	__BEGIN__;
	
	float *tabSin = 0;
	float *tabCos = 0;
	const uchar* source;
	int sstep, scols, srows;
	
	uchar* dest;
	int dstep, dcols, drows, delem_size, half_dcols;
	
	float theta, inv_rho;

	double ang;
	int r, val, shift;
	int i, j, n;

	CvMat stmp, *img;
	CvMat dtmp, *dst;

	CV_CALL( img = cvGetMat( src_image, &stmp ));
	CV_CALL( dst = cvGetMat( dst_image, &dtmp ));

	if (CV_MAT_TYPE(img->type) != CV_8UC1) 
		CV_ERROR( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
	if (CV_MAT_TYPE(dst->type) != CV_32SC1) 
		CV_ERROR( CV_StsBadArg, "The destination image must be 32-bit, single-channel" );

////////////////////////////////

	source = img->data.ptr;
	sstep = img->step;
	scols = img->cols;
	srows = img->rows;

	dest = dst->data.ptr;
	delem_size = CV_ELEM_SIZE(CV_32SC1);
	drows = dst->rows; //numangle
	dcols = dst->cols;
	dstep = dst->step;
	half_dcols = dcols / 2;
	
	theta = CV_PI / drows;
	inv_rho =  double(dcols) / (sqrt(scols*scols + srows*srows) * 2.0 + 10.0);
	
	CV_CALL( tabSin = (float*)cvAlloc( sizeof(tabSin[0]) * drows ));
	CV_CALL( tabCos = (float*)cvAlloc( sizeof(tabCos[0]) * drows ));
	cvSetZero(dst);
	cvSet(dst, cvScalarAll(0));

	for(ang = 0, i = 0; i < drows; ang += theta, i++ ) {
		tabSin[i] = (float)(sin(ang) * inv_rho);
		tabCos[i] = (float)(cos(ang) * inv_rho);
	}

	for(i = 0; i < srows; i++ )
		for(j = 0; j < scols; j++ ) {
			if (val = source[i * sstep + j]) 
				for(n = 0, shift = 0; n < drows; n++, shift += dstep) {
					r = cvRound( j * tabCos[n] + i * tabSin[n] ) + half_dcols;
        			*((int*)(dest + (size_t)shift + r*delem_size)) += val;
				}
		}
	
	__END__;
}


